/*
 * @Author: liusheng
 * @Date: 2022-04-12 10:23:21
 * @LastEditors: liusheng
 * @LastEditTime: 2022-04-12 19:26:10
 * @Description: 剑指 Offer II 024. 反转链表
 * email:liusheng613@126.com
 * Copyright (c) 2022 by liusheng/liusheng, All Rights Reserved. 
 * 
 * 
 * 剑指 Offer II 024. 反转链表
给定单链表的头节点 head ，请反转链表，并返回反转后的链表的头节点。

 

示例 1：


输入：head = [1,2,3,4,5]
输出：[5,4,3,2,1]
示例 2：


输入：head = [1,2]
输出：[2,1]
示例 3：

输入：head = []
输出：[]
 

提示：

链表中节点的数目范围是 [0, 5000]
-5000 <= Node.val <= 5000
 

进阶：链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题？

 

注意：本题与主站 206 题相同： https://leetcode-cn.com/problems/reverse-linked-list/
 */

struct ListNode {
      int val;
      ListNode *next;
      ListNode() : val(0), next(nullptr) {}
      ListNode(int x) : val(x), next(nullptr) {}
      ListNode(int x, ListNode *next) : val(x), next(next) {}
};

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (!head)
        {
            return head;
        }
        
        //double point the p2->next = p1 is redundant
        //see solution 2 for the optimition solution
        ListNode * pre = nullptr;
        ListNode * p1 = head;
        ListNode * p2 = head->next;
        while (p1 && p2)
        {
            ListNode * next = p2->next;
            p1->next = pre;
            p2->next = p1;

            pre = p1;
            p1 = p2;
            p2 = next;
        }

        return p1;
    }
};

class Solution2 {
public:
    ListNode* reverseList(ListNode* head) {
        if (!head || !head->next)
        {
            return head;
        }
        
        ListNode * pre = nullptr;
        ListNode * curr = head;
        while (curr)
        {
            ListNode * next = curr->next;
            curr->next = pre;

            pre = curr;
            curr =  next;
        }

        return pre;
    }
};

class Solution3 {
public:
    ListNode* reverseList(ListNode* head) {
        if (!head || !head->next)
        {
            return head;
        }

        ListNode * reversedHead = reverseList(head->next);

        //head->next- is the reversed tail
        head->next->next = head;

        //head is the current node
        head->next = nullptr;

        return reversedHead;
    }
};

/*
92. Reverse Linked List II
Medium

5919

278

Add to List

Share
Given the head of a singly linked list and two integers left and right where left <= right, reverse the nodes of the list from position left to position right, and return the reversed list.

 

Example 1:


Input: head = [1,2,3,4,5], left = 2, right = 4
Output: [1,4,3,2,5]
Example 2:

Input: head = [5], left = 1, right = 1
Output: [5]
 

Constraints:

The number of nodes in the list is n.
1 <= n <= 500
-500 <= Node.val <= 500
1 <= left <= right <= n
 

Follow up: Could you do it in one pass?
*/

class Solution4 {
public:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        if (!head || !head->next)
        {
            return head;
        }
        
        ListNode * beforeReversedNode =nullptr;
        ListNode *reverseFirstNode = head;
        for (int i = 1; i < left; ++i)
        {
            beforeReversedNode = reverseFirstNode;
            reverseFirstNode = reverseFirstNode->next;
        }
        
        
        ListNode * p2 = reverseFirstNode;
        ListNode * pre2 = nullptr;
        for (int i = left; i <= right; ++i)
        {
            ListNode * next = p2->next;
            p2->next = pre2;
            
            pre2 = p2;
            p2 = next;
        }
        
        if (beforeReversedNode)
        {
            beforeReversedNode->next = pre2;
        }
        else
        {
            //reverse from 1th,so the head now be the last reversed value
            head = pre2;
        }
        
        
        //p2 now is the node after the last reversed node
        reverseFirstNode->next = p2;
        
        return head;
    }
};
